package cn.janescott.framework.core.utils;

import cn.janescott.framework.core.exception.MyException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * json工具类
 *
 * @author scott
 * @date 2019/2/22
 */
public final class JsonUtils {
    private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class);

    private static final ObjectMapper OM = new ObjectMapper();

    static {
        /*  */
        OM.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
        /* 反序列化时，如果多了其他属性，不抛出异常 */
        OM.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }


    private JsonUtils() {
    }

    public static <T> String toJson(T obj) {
        if (null == obj) {
            return null;
        }
        try {
            return obj instanceof String ? (String) obj : OM.writeValueAsString(obj);
        } catch (Exception ex) {
            LoggerUtils.error(logger, () -> ex);
            throw new MyException(ex.getMessage(), ex);
        }
    }

    public static <T> String toJsonPretty(T obj) {
        if (null == obj) {
            return null;
        }
        try {
            return obj instanceof String ? (String) obj :
                    OM.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (Exception ex) {
            LoggerUtils.error(logger, () -> ex);
            throw new MyException(ex.getMessage(), ex);
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T fromJson(String str, Class<T> clazz) {
        if (isEmpty(str)) {
            return (T)null;
        }
        try {
            return clazz.equals(String.class) ? (T) str : OM.readValue(str, clazz);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            throw new MyException(ex.getMessage(), ex);
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T fromJson(String str, TypeReference<T> tTypeReference) {
        if (isEmpty(str)) {
            return null;
        }
        try {
            return (T) (tTypeReference.getType().equals(String.class) ? str : OM.readValue(str, tTypeReference));
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            throw new MyException(ex.getMessage(), ex);
        }
    }

    public static <T> T fromJsonToCollection(String str, Class<?> collectionClazz, Class<?>... elementClass) {
        JavaType type = OM.getTypeFactory().constructParametricType(collectionClazz, elementClass);
        try {
            return OM.readValue(str, type);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            throw new MyException(ex.getMessage(), ex);
        }
    }

    /**
     * 字符串判空
     * null || empty || blank
     *
     * @param str
     * @return
     */
    private static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }
}
